package com.ja.rfid.component;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Kisen
 * @email liuqs@jaid.cn
 * @date 2022/11/16 11:28
 * @detail websocket server端
 * clientId格式: 机器socket端口@时间戳
 * 8092,8093,8094端口分别对应1号机、2号机、3号机
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{clientId}")
public class WebSocketServer {

    //用来存放每个客户端对应的WebSocket对象
    public static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    //当前连接客户端的用户唯一标识
    private String clientId;

    /**
     * 连接建立成功调用的方法
     *
     * @param session
     * @param clientId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("clientId") String clientId) {
        this.session = session;
        this.clientId = clientId;
        // clientId是用来表示唯一客户端，如果需要指定发送，需要指定发送通过clientId来区分
        webSocketMap.put(clientId, this);
        log.info("[WebSocket]客户端{}连接成功，客户端标识：{}，当前在线连接数为：{}", session.getId(), clientId, webSocketMap.size());
    }

    /**
     * 连接关闭调用的方法
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        webSocketMap.remove(this.clientId);
        log.info("[WebSocket]客户端{}连接断开，客户端标识：{}，当前在线连接数为：{}", session.getId(), clientId, webSocketMap.size());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到客户端{} 的消息：{}", session.getId(), message);
        //心跳检测响应
        if (StringUtils.equalsIgnoreCase("ping", message)) {
            sendMessage("pong");
            log.info("[WebSocket]服务端 已回复客户端{} 的心跳检测: pong", session.getId());
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("客户端{} 发生错误：{}", session.getId(), error);
    }

    /**
     * 实现服务器主动推送
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("客户端{} 发生消息({})失败：{}", session.getId(), message, e);
            throw new RuntimeException(e);
        }
    }

}
